{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "142ce3d4",
   "metadata": {},
   "source": [
    "# 구조화된 출력을 사용하는 체인(with_structured_output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a43b92b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# API 키를 환경변수로 관리하기 위한 설정 파일\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# API 키 정보 로드\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dcf8bb5b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LangSmith 추적을 설정합니다. https://smith.langchain.com\n",
    "# !pip install langchain-teddynote\n",
    "from langchain_teddynote import logging\n",
    "\n",
    "# 프로젝트 이름을 입력합니다.\n",
    "logging.langsmith(\"Structured-Output-Chain\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19066592",
   "metadata": {},
   "source": [
    "특정 주제에 대한 4지선다형 퀴즈를 생성하는 과정을 구현합니다.\n",
    "\n",
    "`Quiz` 클래스는 퀴즈의 질문, 난이도, 그리고 네 개의 선택지를 정의합니다.\n",
    "\n",
    "`ChatOpenAI` 인스턴스는 GPT-4o 모델을 사용하여 자연어 처리를 수행하고, `ChatPromptTemplate`는 퀴즈 생성을 위한 대화형 프롬프트를 정의합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "193e17a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains.openai_functions import create_structured_output_runnable\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "from typing import List\n",
    "\n",
    "\n",
    "class Quiz(BaseModel):\n",
    "    \"\"\"4지선다형 퀴즈의 정보를 추출합니다\"\"\"\n",
    "\n",
    "    question: str = Field(..., description=\"퀴즈의 질문\")\n",
    "    level: str = Field(\n",
    "        ..., description=\"퀴즈의 난이도를 나타냅니다. (쉬움, 보통, 어려움)\"\n",
    "    )\n",
    "    options: List[str] = Field(..., description=\"퀴즈의 4개의 선택지 입니다.\")\n",
    "\n",
    "\n",
    "llm = ChatOpenAI(model=\"gpt-4o\", temperature=0.1)\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"You're a world-famous quizzer and generates quizzes in structured formats.\",\n",
    "        ),\n",
    "        (\n",
    "            \"human\",\n",
    "            \"TOPIC 에 제시된 내용과 관련한 4지선다형 퀴즈를 출제해 주세요. 만약, 실제 출제된 기출문제가 있다면 비슷한 문제를 만들어 출제하세요.\"\n",
    "            \"단, 문제에 TOPIC 에 대한 내용이나 정보는 포함하지 마세요. \\nTOPIC:\\n{topic}\",\n",
    "        ),\n",
    "        (\"human\", \"Tip: Make sure to answer in the correct format\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "# 구조화된 출력을 위한 모델 생성\n",
    "llm_with_structured_output = llm.with_structured_output(Quiz)\n",
    "\n",
    "# 퀴즈 생성 체인 생성\n",
    "chain = prompt | llm_with_structured_output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "222bce02",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 퀴즈 생성을 요청합니다.\n",
    "generated_quiz = chain.invoke({\"topic\": \"ADSP(데이터 분석 준전문가) 자격 시험\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9aded677",
   "metadata": {},
   "source": [
    "생성된 퀴즈를 출력합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ca9b6c38",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 생성된 퀴즈 출력\n",
    "print(f\"{generated_quiz.question} (난이도: {generated_quiz.level})\\n\")\n",
    "for i, opt in enumerate(generated_quiz.options):\n",
    "    print(f\"{i+1}) {opt}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
